package org.yunai.protobuf.conf;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * 消息配置
 * User: yunai
 * Date: 13-3-12
 * Time: 下午11:56
 */
public class MessageConfig {

    private static final String CONFIG_ROOT = "MessageConfig";

    private static final String MESSAGE_ROOT = "Message";
    private static final String MESSAGE_ATTRIBUTE_ID = "id";
    private static final String MESSAGE_ATTRIBUTE_NAME = "name";
    private static final String MESSAGE_ATTRIBUTE_FROM_SIDE = "fromSide";
    private static final String MESSAGE_ATTRIBUTE_TO_SIDE = "toSide";
    private static final String MESSAGE_ATTRIBUTE_DESC = "desc";

    public static List<Message> messages;

    public static class Message implements CodeClass {

        /**
         * 消息编号
         */
        private Integer id;
        /**
         * 消息名
         */
        private String name;
        /**
         * 发起端
         */
        private String fromSide;
        /**
         * 接收端
         */
        private String toSide;
        /**
         * 描述
         */
        private String desc;
        /**
         * 参数列表
         */
        private List<Param> params;

        public Integer getId() {
            return id;
        }

        public void setId(Integer id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getFromSide() {
            return fromSide;
        }

        public void setFromSide(String fromSide) {
            this.fromSide = fromSide;
        }

        public String getToSide() {
            return toSide;
        }

        public void setToSide(String toSide) {
            this.toSide = toSide;
        }

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        public List<Param> getParams() {
            return params;
        }

        public void setParams(List<Param> params) {
            this.params = params;
        }

        public String getPackPrefix() {
            return fromSide + "_" + toSide;
        }

        public String getClassName() {
            return fromSide + "_" + toSide + "_" + name;
        }

        @Override
        public List<Param> obtainParams() {
            return getParams();
        }

        @Override
        public String obtainClassName() {
            return fromSide + "_" + toSide + "_" + name;
        }
    }

    public static void load() {
        InputStream is = null;
        try {
            // 创建InputStream
            URL url = Thread.currentThread().getContextClassLoader().getResource(Config.filePath);
            if (url == null) {
                throw new FileNotFoundException(url + "文件不存在！");
            }
            is = new FileInputStream(url.getFile());

            // XML解析
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = builder.parse(is);

            // 解析MessageConfig节点
            NodeList messageConfigNodes = doc.getElementsByTagName(CONFIG_ROOT);
            if (messageConfigNodes.getLength() > 1) {
                throw new SAXException("<" + CONFIG_ROOT + ">只允许有一个！");
            }
            Node messageConfigNode = messageConfigNodes.item(0);

            // 解析Message节点
            messages = new ArrayList<Message>();
            NodeList messageNodes = messageConfigNode.getChildNodes();
            for (int i = 0, len = messageNodes.getLength(); i < len; i++) {
                Node messageNode = messageNodes.item(i);
                if (!MESSAGE_ROOT.equals(messageNode.getNodeName())) {
                    continue;
                }
                parseMessageNode(messageNode);
            }

        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void parseMessageNode(Node node) {
        Message message = new Message();
        NamedNodeMap attributes  = node.getAttributes();
        message.setId(Integer.valueOf(attributes.getNamedItem(MESSAGE_ATTRIBUTE_ID).getNodeValue()));
        message.setName(attributes.getNamedItem(MESSAGE_ATTRIBUTE_NAME).getNodeValue());
        message.setFromSide(attributes.getNamedItem(MESSAGE_ATTRIBUTE_FROM_SIDE).getNodeValue());
        message.setToSide(attributes.getNamedItem(MESSAGE_ATTRIBUTE_TO_SIDE).getNodeValue());
        message.setDesc(attributes.getNamedItem(MESSAGE_ATTRIBUTE_DESC).getNodeValue());
        messages.add(message);

        // 解析Param节点
        NodeList paramNodes = node.getChildNodes();
        List<Param> params = new ArrayList<Param>();
        message.setParams(params);
        for (int i = 0, len = paramNodes.getLength(); i < len; i++) {
            Node paramNode = paramNodes.item(i);
            if (!Param.CONFIG_ROOT.equals(paramNode.getNodeName())) {
                continue;
            }
            Param param = Param.parseParamNode(message, paramNode);
            params.add(param);
        }
    }

}
